#include "io_proc.h"
#include "pin_map.h"
#include "system_init.h"
#include <esp_log.h>
#include <driver/i2c_master.h>
#include <freertos/FreeRTOS.h>

#define TAG "IO_PROC"
// PcaIO pca_io;

// void pac_io_init(void)
// {
//     pca_io.init(esp_i2c_bus_handle_get(I2C_NUM_0));
//     // lcd cs init
//     pca_io.set_pin_dir(PIN_LCD_CS, PcaIO::PIN_OUTPUT);
//     pca_io.write_pin(PIN_LCD_CS, PcaIO::PIN_LOW); // Set CS pin high
// }

i2c_master_dev_handle_t m_i2c_dev;

// 读取PCA9557寄存器的值
esp_err_t pca9557_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
{
    return i2c_master_transmit_receive(m_i2c_dev, &reg_addr, 1, data, len, 1000 / portTICK_PERIOD_MS);
}

// 给PCA9557的寄存器写值
esp_err_t pca9557_register_write_byte(uint8_t reg_addr, uint8_t data)
{
    uint8_t write_buf[2] = {reg_addr, data};

    return i2c_master_transmit(m_i2c_dev, write_buf, sizeof(write_buf), 1000 / portTICK_PERIOD_MS);
}

// 初始化PCA9557 IO扩展芯片
void pca9557_init(void)
{
    i2c_device_config_t i2c_config;
    i2c_config.dev_addr_length = I2C_ADDR_BIT_LEN_7;
    i2c_config.device_address = PCA9557_SENSOR_ADDR;
    i2c_config.scl_speed_hz = 100000;
    i2c_config.scl_wait_us = 1000;

    if (m_i2c_dev == NULL) {
        i2c_master_bus_add_device(esp_i2c_bus_handle_get(0), &i2c_config, &m_i2c_dev);
    }

    if (!m_i2c_dev) {
        ESP_LOGE(TAG, "Failed to add I2C device");
        return;
    }

    // 写入控制引脚默认值 DVP_PWDN=1  PA_EN = 0  LCD_CS = 1
    pca9557_register_write_byte(PCA9557_OUTPUT_PORT, 0x05);  
    // 把PCA9557芯片的IO1 IO1 IO2设置为输出 其它引脚保持默认的输入
    pca9557_register_write_byte(PCA9557_CONFIGURATION_PORT, 0xf8); 
}

// 设置PCA9557芯片的某个IO引脚输出高低电平
esp_err_t pca9557_set_output_state(uint8_t gpio_bit, uint8_t level)
{
    uint8_t data;
    esp_err_t res = ESP_FAIL;

    pca9557_register_read(PCA9557_OUTPUT_PORT, &data, 1);
    res = pca9557_register_write_byte(PCA9557_OUTPUT_PORT, SET_BITS(data, gpio_bit, level));

    return res;
}

// 控制 PCA9557_LCD_CS 引脚输出高低电平 参数0输出低电平 参数1输出高电平 
void lcd_cs(uint8_t level)
{
    // pca_io.write_pin(PIN_LCD_CS, PcaIO::PinValue(level)); // Set CS pin high
    pca9557_set_output_state(LCD_CS_GPIO, level);
}

// 控制 PCA9557_PA_EN 引脚输出高低电平 参数0输出低电平 参数1输出高电平 
void pa_en(uint8_t level)
{
    pca9557_set_output_state(PA_EN_GPIO, level);
}

// 控制 PCA9557_DVP_PWDN 引脚输出高低电平 参数0输出低电平 参数1输出高电平 
void dvp_pwdn(uint8_t level)
{
    pca9557_set_output_state(DVP_PWDN_GPIO, level);
}